package cn.com.hhrcw.enterprise.web;

import cn.com.hhrcw.enterprise.params.EnInfoParams;
import cn.com.hhrcw.enterprise.params.LoginUserParams;
import cn.com.hhrcw.enterprise.params.PiInfoParams;
import cn.com.hhrcw.enterprise.service.EnterpriseService;
import cn.com.hhrcw.enterprise.vo.EnInfoVO;
import cn.com.hhrcw.enterprise.vo.PiInfoVO;
import cn.com.hhrcw.enterprise.vo.UserAndComInfoVo;
import cn.com.hhrcw.entity.*;
import cn.com.hhrcw.mapstruct.EnEnInfoConvert;
import cn.com.hhrcw.mapstruct.EnPiInfoConvert;
import cn.com.hhrcw.service.*;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.enums.Roles;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.PasswordUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.function.Function;

/**
 * 公司注册
 *
 * @author: JD
 * @create: 2020-11-06 14:45
 **/
@RestController
@RequestMapping("/en/reg")
@Slf4j
public class RegController {

    @Autowired
    private IPiInfoService pinfoService;

    @Autowired
    private EnPiInfoConvert enPiInfoConvert;

    @Autowired
    private IEnInfoService enInfoService;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    EnterpriseService enterpriseService;

    @Autowired
    private IEnInfoService ennfoService;

    @Autowired
    private EnEnInfoConvert enEnInfoConvert;

    @Autowired
    private ISysUserDepartService userDepartService;

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    IFileService fileService;

    @Autowired
    private IOpJobService jobService;

    @Autowired
    IOpDeliveryHistoryService historyService;

    @Autowired
    private ISysUserDepartService sysUserDepartService;

    @Autowired
    private EnPiInfoConvert piInfoConvert;

    @Autowired
    private ISysBaseAPI sysBaseApi;

    @Autowired
    IPiInfoService piInfoService;

    @Autowired
    ISysUserService userService;

    /**
     * 转让管理员
     *
     * @param id 被授权人id
     * @return
     */
    @GetMapping("/transRole")
    @AutoLog(logType = 2, ty = "update", value = "转让管理员")
    public Result trans(String id) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        PiInfo info = this.pinfoService.lambdaQuery().eq(PiInfo::getUserId, sysUser.getId()).eq(PiInfo::getEnRoleType, 1).one();
        Assert.notNull(info, "您不是管理员,不能转让权限");
        boolean res = pinfoService.trans(sysUser.getId(), id);
        return Result.ok(res);
    }

    /**
     * 个人id查询个人信息
     *
     * @param id 数据id
     * @return
     */
    @GetMapping(value = "/queryById")
    @AutoLog(logType = 2, ty = "visit", value = "个人信息查询")
    @ApiOperation(value = "根据id查询", notes = "根据id查询")
    public Result<PiInfoVO> queryById(String id) {
        PiInfo piInfo = pinfoService.lambdaQuery().eq(PiInfo::getUserId, id).eq(PiInfo::getDelFlag, false).one();
        Assert.notNull(piInfo, "数据不存在");
        return Result.ok(piInfoConvert.toVO(piInfo));
    }

    /**
     * 同事列表
     *
     * @param params 请求参数
     * @return
     */
    @GetMapping(value = "/list")
    @AutoLog(logType = 2, ty = "visit", value = "同事列表查询")
    @ApiOperation(value = "分页列表查询", notes = "分页列表查询")
    public Result<Page<PiInfoVO>> list(PiInfoParams params, HttpServletRequest request) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        SysUserDepart userDepart = userDepartService.lambdaQuery().eq(SysUserDepart::getUserId, sysUser.getId()).one();
        List<SysUserDepart> userDeparts = userDepartService.lambdaQuery().eq(SysUserDepart::getDepId, userDepart.getDepId()).list();
        if (CollectionUtils.isEmpty(userDeparts)) {
            return Result.ok(new Page<>());
        }
        List<String> ids = new ArrayList<>();
        userDeparts.forEach(e -> {
            ids.add(e.getUserId());
        });
        LambdaQueryWrapper<PiInfo> queryWrapper = QueryGenerator.initQueryWrapper(enPiInfoConvert.toEntity(params), request.getParameterMap()).lambda();
        queryWrapper.eq(PiInfo::getDelFlag, false);
        queryWrapper.orderByDesc(PiInfo::getCreateTime);
        queryWrapper.in(PiInfo::getUserId, ids);

        if (StringUtils.isNotBlank(params.getQueryValue())) {
            queryWrapper.and(lambdaQueryWrapper -> lambdaQueryWrapper.like(PiInfo::getName, params.getQueryValue()).or().like(PiInfo::getEmail, params.getQueryValue()).or().like(PiInfo::getPhone, params.getQueryValue()));
        }

        IPage<PiInfo> page = pinfoService.page(params.page(), queryWrapper);
        //分页结果转换器
        Function<PiInfo, PiInfoVO> fun = piInfo -> {
            PiInfoVO vo = enPiInfoConvert.toVO(piInfo);
            List<OpJob> jobCount = jobService.lambdaQuery().eq(OpJob::getDelFlag, false).eq(OpJob::getRecruitmentState, 0).eq(OpJob::getCreateBy, piInfo.getUserId()).list();
            vo.setOnlineJobCount(CollectionUtils.isEmpty(jobCount) ? 0 : jobCount.size());
            if (!CollectionUtils.isEmpty(jobCount)) {
                List<String> jobId = new ArrayList<>();
                jobCount.forEach(e -> {
                    jobId.add(e.getId());
                });
                Integer seven = historyService.seven(jobId);
                vo.setSevenCount(seven);
            }
            return vo;
        };

        return Result.ok((Page) page.convert(fun));
    }

    /**
     * 批量删除
     *
     * @param id 数据id
     * @return
     */
    @GetMapping(value = "/delete")
    @AutoLog(logType = 2, ty = "delete", value = "同事删除")
    @ApiOperation(value = "批量删除", notes = "批量删除")
    @RequiresPermissions("piInfo:delete")
    public Result delete(String[] id) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        PiInfo info = this.pinfoService.lambdaQuery().eq(PiInfo::getUserId, sysUser.getId()).eq(PiInfo::getEnRoleType, 1).one();
        Assert.notNull(info, "您不是管理员,不能删除同事");
        LambdaQueryWrapper<SysUserDepart> wrapper = Wrappers.<SysUserDepart>lambdaQuery().eq(SysUserDepart::getDepId, sysUser.getCompanyId()).in(SysUserDepart::getUserId, id);
        return this.userDepartService.remove(wrapper) ? Result.ok() : Result.error("删除失败");
    }

    /**
     * 注册-添加公司信息
     *
     * @param params 请求参数
     * @return
     */
    @PostMapping(value = "/addComInfo")
    @AutoLog(logType = 2, ty = "insert", value = "公司注册")
    @ApiOperation(value = "添加", notes = "添加")
    @Deprecated
    public Result<?> add(@RequestBody @Valid EnInfoParams params) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        int count = enInfoService.lambdaQuery().eq(EnInfo::getEnName, params.getEnName()).eq(EnInfo::getDelFlag, false).count();
        Assert.isFalse(count > 0, "企业名称已存在");
        LoginUser sysUser = sysBaseApi.getUserByName(loginUser.getUsername());
        EnInfo enInfo = enEnInfoConvert.toEntity(params);
        enInfo.setCreateBy(sysUser.getId());
        enInfo.setCreateTime(DateUtil.date());
        enInfo.setDelFlag(false);
        enInfo.setState(1);
        enInfo.setActFlag(true);
        enInfo.setPostNum(0);
        enInfo.setDeliverNum(0);
        boolean saved = ennfoService.save(enInfo);
        if (saved) {
            userDepartService.referenceUser(loginUser.getId(), enInfo.getId());
        }
        jdbcTemplate.update("insert into sys_depart (id,depart_name,org_category,org_code,create_by,create_time) value (?,?,?,?,?,?)", new Object[]{enInfo.getId(), params.getEnName(), "1", " ", sysUser.getId(), new Date()});
        SecurityUtils.getSubject().logout();
        return saved ? Result.ok(enInfo.getId()) : Result.error("添加失败");
    }

    /**
     * 编辑企业信息
     *
     * @param params 请求参数
     * @return
     */
    @PostMapping(value = "/editComInfo")
    @AutoLog(logType = 2, ty = "update", value = "公司信息编辑")
    @ApiOperation(value = "编辑", notes = "编辑")
    public Result<?> edit(@RequestBody @Valid EnInfoParams params) {
        int count = enInfoService.lambdaQuery().ne(EnInfo::getId, params.getId()).eq(EnInfo::getEnName, params.getEnName()).eq(EnInfo::getDelFlag, false).count();
        Assert.isFalse(count > 0, "企业名称已存在");
        EnInfo enInfo = enEnInfoConvert.toEntity(params);
        enInfo.setEnGrade(params.getEnGrade());
        enInfo.setAffUnit(params.getAffUnit());
        enInfo.setUpdateTime(DateUtil.date());
        boolean updated = ennfoService.updateById(enInfo);
        if (updated) {
            List<SysUserDepart> departs = sysUserDepartService.lambdaQuery().eq(SysUserDepart::getDepId, enInfo.getId()).list();
            PiInfo piInfo = piInfoService.lambdaQuery().in(PiInfo::getUserId, departs.stream().map(SysUserDepart::getUserId).toArray()).eq(PiInfo::getEnRoleType, 1).eq(PiInfo::getDelFlag, false).one();
            if (piInfo != null) {
                SysUser user = userService.getById(piInfo.getUserId());
                if (StringUtils.isNotBlank(params.getPersonalEmail())) {
                    piInfo.setEmail(params.getPersonalEmail());
                    user.setEmail(params.getPersonalEmail());
                }
                if (StringUtils.isNotBlank(params.getPersonalName())) {
                    piInfo.setName(params.getPersonalName());
                    user.setRealname(params.getPersonalName());
                }
                userService.updateById(user);
                pinfoService.updateById(piInfo);
            }
        }
        return updated ? Result.ok() : Result.error("编辑失败");
    }

    /**
     * 注册-信息核对
     *
     * @return
     */
    @GetMapping("/configInfo")
    public Result<UserAndComInfoVo> config() {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        LambdaQueryWrapper<PiInfo> piInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        piInfoLambdaQueryWrapper.eq(PiInfo::getDelFlag, false).eq(PiInfo::getUserId, sysUser.getId());
        PiInfo info = pinfoService.getOne(piInfoLambdaQueryWrapper);
        PiInfoVO piInfoVO = enPiInfoConvert.toVO(info);
        String comId = jdbcTemplate.queryForObject("select dep_id from  sys_user_depart where user_id = ?", new Object[]{sysUser.getId()}, String.class);
        LambdaQueryWrapper<EnInfo> enInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        enInfoLambdaQueryWrapper.eq(EnInfo::getDelFlag, false).eq(EnInfo::getId, comId);
        EnInfo enInfo = enInfoService.getOne(enInfoLambdaQueryWrapper);
        EnInfoVO enInfoVO = enEnInfoConvert.toVO(enInfo);

        return Result.ok(new UserAndComInfoVo(piInfoVO, enInfoVO));
    }

    /**
     * 注册-新增个人信息
     *
     * @param params 请求参数
     * @return
     */
    @PostMapping(value = "/addPcInfo")
    @AutoLog(logType = 2, ty = "insert", value = "添加个人信息")
    @ApiOperation(value = "添加", notes = "添加")
    public Result<?> add(@RequestBody @Valid PiInfoParams params) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        PiInfo piInfo = null;

        if (sysUser != null && params.getIsCreate() != null && params.getIsCreate()) {
            SysUser member = this.sysUserService.lambdaQuery().eq(SysUser::getPhone, params.getPhone() + "@ent").one();
            if (member != null) {
                SysUserDepart userDepart = this.userDepartService.lambdaQuery().eq(SysUserDepart::getUserId, member.getId()).one();
                Assert.isNull(userDepart, "该手机号已经注册企业用户，请解绑后再注册");
                piInfo = this.pinfoService.lambdaQuery().eq(PiInfo::getUserId, member.getId()).one();
                this.pinfoService.lambdaUpdate().eq(PiInfo::getUserId, member.getId()).set(PiInfo::getEnRoleType, 0).update();
            } else {
                String username = StrUtil.format("{}@ent", Long.toString(Convert.toLong(params.getPhone()), 32));
                String phone = StrUtil.format("{}@ent", params.getPhone());
                member = new SysUser();
                member.setPhone(phone);
                member.setUsername(username);
                member.setDelFlag(false);
                member.setStatus(1);
                String salt = RandomStringUtils.randomAlphanumeric(8);
                member.setSalt(salt);
                member.setPassword(PasswordUtil.encrypt(member.getUsername(), salt, member.getSalt()));
                this.sysUserService.save(member);
                piInfo = enPiInfoConvert.toEntity(params);
                piInfo.setCreateBy(sysUser.getId());
                piInfo.setCreateTime(DateUtil.date());
                piInfo.setDelFlag(false);
                piInfo.setUserId(member.getId());
                piInfo.setUsername(member.getUsername());
                piInfo.setPhone(member.getPhone());
                piInfo.setCreateTime(DateTime.now());
                piInfo.setCreateBy(sysUser.getId());
                piInfo.setDelFlag(false);
                piInfo.setEnRoleType(0);
                piInfo.setRoleType("1,");
                pinfoService.save(piInfo);
            }
            this.userDepartService.referenceUser(member.getId(), sysUser.getCompanyId());
            this.sysBaseApi.addRole(member.getId(), Roles.ENT);
        } else if (sysUser != null) {
            //注册使用 2020年12月31日11:37:31 废弃，已经 移动到 RegV2Controller
            piInfo = this.pinfoService.lambdaQuery().eq(PiInfo::getUserId, sysUser.getId()).one();
            piInfo.setIdNumber(params.getIdNumber());
            piInfo.setBackFileid(params.getBackFileid());
            piInfo.setName(params.getName());
            piInfo.setPositiveFileid(params.getPositiveFileid());
            piInfo.setEnRoleType(1);
            pinfoService.updateById(piInfo);
        }
        return Result.ok(piInfo.getId());
    }

    /**
     * 编辑个人信息
     *
     * @param params 请求参数
     * @return
     */
    @PostMapping(value = "/editPcInfo")
    @AutoLog(logType = 2, ty = "update", value = "个人信息编辑")
    @ApiOperation(value = "编辑", notes = "编辑")
    public Result<?> edit(@RequestBody @Valid PiInfoParams params) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        PiInfo piInfo = enPiInfoConvert.toEntity(params);
        //不修改手机号
        piInfo.setPhone(null);
        piInfo.setUsername(sysUser.getUsername());
        boolean updated = pinfoService.updateById(piInfo);
        return updated ? Result.ok() : Result.error("编辑失败");
    }

    /**
     * 修改手机号
     *
     * @param params 请求参数
     * @return
     */
    @PostMapping(value = "/modify_phone")
    @AutoLog(logType = 2, ty = "update", value = "修改手机号")
    public Result<?> modifyPhone(@RequestBody @Valid LoginUserParams params) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        Assert.isFalse(StrUtil.equals(sysUser.getPhone(), params.getMobile()), "新号码不能与原号码一样");
        String username = Long.toString(Convert.toLong(params.getMobile()), 32) + "@ent";
        String phone = params.getMobile() + "@ent";

        int exists = this.sysUserService.lambdaQuery().eq(SysUser::getPhone, phone).count();
        Assert.isTrue(exists == 0, "手机号已注册");
        this.sysUserService.lambdaUpdate().eq(SysUser::getId, sysUser.getId())
                .set(SysUser::getUsername, username)
                .set(SysUser::getPhone, phone).update();
        this.pinfoService.lambdaUpdate().eq(PiInfo::getUserId, sysUser.getId())
                .set(PiInfo::getUsername, username)
                .set(PiInfo::getPhone, phone).update();
        sysUser.setPhone(params.getMobile());
        return Result.ok();
    }
}
